from abc import ABC, abstractmethod
from typing import Optional, Any, Dict, List, Union
from pydantic import BaseModel, Field, HttpUrl
from threading import Lock
import requests
from Logger import Logger
from llm.EmbeddingClientBase import EmbeddingResponse, EmbeddingClientBase

logger = Logger.get_logger(__name__)

class SiliconFlowEmbeddingClient(EmbeddingClientBase):
    """SiliconFlow 嵌入服务实现"""
    
    def __init__(
        self,
        token: str,
        model: str = "BAAI/bge-large-zh-v1.5",
        base_url: HttpUrl = "https://api.siliconflow.cn",
        api_version: str = "v1",
        encoding_format: str = "float",
        timeout: int = 30
    ):
        """
        初始化客户端
        
        :param token: API token
        :param model: 模型名称
        :param base_url: API基础URL
        :param api_version: API版本
        :param encoding_format: 编码格式
        :param timeout: 请求超时时间(秒)
        """
        self.token = token
        self.model = model
        self.base_url = f"{base_url}/{api_version}"
        self.encoding_format = encoding_format
        self.timeout = timeout
        self.lock = Lock()
        self.session = requests.Session()
    
    def get_embeddings(self, input_text: Union[str, List[str]]) -> EmbeddingResponse:
        """
        获取嵌入向量 (线程安全)
        
        :param input_text: 输入文本或文本列表
        :return: EmbeddingResponse
        """
        url = f"{self.base_url}/embeddings"
        headers = {
            "Authorization": f"Bearer {self.token}",
            "Content-Type": "application/json"
        }
        
        payload = {
            "model": self.model,
            "input": input_text,
            "encoding_format": self.encoding_format
        }
        
        try:
            # 使用锁确保线程安全
            with self.lock:
                response = self.session.post(
                    url,
                    json=payload,
                    headers=headers,
                    timeout=self.timeout
                )
                response.raise_for_status()
                # 检查响应中是否有错误
                if response.status_code != 200:
                    logger.error(f"获取embedding失败: {response.text}")
                    return None
                response = EmbeddingResponse(**response.json())
                # 从响应中获取embedding向量
                if response.data and len(response.data) > 0:
                    return response.data[0].get('embedding')
                return None        
        except requests.exceptions.RequestException as e:
            logger.error(f"请求失败: {str(e)}")
            return None
        except ValueError as e:
            logger.error(f"响应解析失败: {str(e)}")
            return None
        except Exception as e:
            logger.error(f"未知错误: {str(e)}")
            return None
